layui.define(function (exports) {
    "use strict";

    // jQuery
    const $ = layui.$

    //dom
    const parser = new DOMParser();

    /**
     * jqGet
     * @param {string} url 
     * @returns string|error
     */
    const jqGet = async function (url) {
        try {
            const res = await $.get(url);
            return res;
        } catch (error) {
            // 处理错误的逻辑
            console.error(`组件页面加载失败: ${url}`);
            // 或者根据具体需求返回特定的值或执行其他错误处理操作
            return null;
        }
    }

    // 组件样式
    let sheet = new CSSStyleSheet()

    // 设置公共样式函数
    const setCommonStyle = async function () {
        let commonStyle = ""
        const commonDiv = document.querySelectorAll(`link[common]`)
        for (let index = 0; index < commonDiv.length; index++) {
            if (commonDiv[index].nodeName == "LINK") {
                commonStyle += await jqGet(commonDiv[index].getAttribute("href"))
            } else {
                continue
            }
        }
        sheet.replaceSync(commonStyle)
    }

    // 设置公共样式
    setCommonStyle()

    /**
     * 创建组件
     * @param {target} tag 标签
     * @param {target} body 组件内容
     * @param {string} scriptBody js脚本内容
     * @param {boolean} isStyle 是否加载全局指定样式
     */
    function Component(tag, body, scriptBody, isStyle) {
        // 影子dom
        const shadowRoot = tag.attachShadow({ mode: 'open' });
        // 加载全局样式
        if (isStyle) {
            shadowRoot.adoptedStyleSheets = [sheet]
        }
        // 声明周期钩子
        shadowRoot.hooks = {
            // 组件挂载
            onReady: () => { },
            // 组件更新
            onChange: () => { }
        }

        // 执行js脚本 
        const fn = new Function("doc", "target", scriptBody)
        fn(shadowRoot, tag)

        // 加载组件内容
        shadowRoot.innerHTML = body.innerHTML;

        // 创建监听对象
        const observer = new MutationObserver(function (mutations) {
            mutations.forEach(function (mutation) {
                shadowRoot.hooks.onChange(mutation)
            });
        });
        // 配置观察选项: 子节点变化、属性变化、子树变化、旧属性值
        const config = {
            childList: true,
            attributes: true,
            subtree: true,
            attributeOldValue: true
        };
        // 执行挂载
        shadowRoot.hooks.onReady()
        // 传入目标节点和观察选项
        observer.observe(shadowRoot, config);
        observer.observe(tag, config);
    }

    let comp = {
        /**
         * 渲染组件
         * @param {string} tag 组件标签
         * @param {string} href 组件路径
         * @param {Document} doc 组件文档对象，默认为当前文档对象
         * @param {boolean} isStyle 是否加载全局指定样式，默认为true
         * @returns {Promise<void>}
         */
        render: async function ({ tag, href, doc = document, isStyle = true }) {
            // 获取组件内容
            const html = await jqGet(href)
            // 解析组件内容
            const body = parser.parseFromString(html, "text/html").body
            // 获取js脚本内容
            const scriptBody = body.querySelector("script")?.textContent ?? "";
            // 删除所有script标签
            body.querySelectorAll("script").forEach((script) => {
                script.remove();
            });

            /**
             * 创建组件
             */
            function createComponent() {
                // 所有组件标签
                const tags = doc.querySelectorAll(tag);
                // 遍历所有组件标签
                for (let i = 0; i < tags.length; i++) {
                    if (!tags[i].shadowRoot) {
                        Component(tags[i], body, scriptBody, isStyle)
                    }
                }
            }

            // 创建监听对象
            const observer = new MutationObserver(() => createComponent());
            // 配置观察选项: 子节点变化、子树变化
            const config = {
                childList: true,
                subtree: true
            };
            observer.observe(doc, config);
            createComponent()
        }
    }

    exports('comp', comp); // 输出模块
})